import CRC from "./CRC16.js";
//写入二进制
function WriteBase(deviceId, value, callback) {
	var serviceId = getApp().globalData.bleObj.serviceId;
	var characteristicId = getApp().globalData.bleObj.characteristicId;
	uni.writeBLECharacteristicValue({
		// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
		deviceId,
		// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
		serviceId,
		// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
		characteristicId,
		// 这里的value是ArrayBuffer类型
		value: value,
		success(res) {
			if (res.errCode == 0 || res.errno == 0) {
				if (callback) {
					callback(res);
				}
			} else {
				console.log(res, '写入二进制success');
			}
		},
		fail(res) {
			console.log(res, '写入二进制fail');
		}
	})
}

//写入读取命令03
function writeToRead(start, len, callback, isAuto = true) {
	var deviceId = getApp().globalData.bleObj.deviceId;
	var state = getApp().globalData.bleObj.state;
	if (deviceId != '' && state) {
		var command = readCommand(start, len);
		WriteBase(deviceId, command, function(res) {
			if (callback) {
				callback(res);
			}
		});
	} else {
		if (!isAuto) {
			//msg(language.b16);
		}
	}
}

//写入写命令06
function writeToWrite(start, value, callback) {
	var deviceId = getApp().globalData.bleObj.deviceId;
	var state = getApp().globalData.bleObj.state;
	if (deviceId != '' && state) {
		var command = writeCommand(start, value);
		WriteBase(deviceId, command, function(res) {
			if (callback) {
				callback(res);
			}
		});
	} else {
		console.log('发送指令失败');
	}
}

const top = '01';
const read = '03';
const write = '06';

//组装读取命令
function readCommand(start, len) {
	var d = top + read + start + len;
	var crc16 = CRC.ToModbusCRC16(d);
	d = d + crc16;

	var typedArray = new Uint8Array(d.match(/[\da-f]{2}/gi).map(function(h) {
		return parseInt(h, 16)
	}));
	//console.log(typedArray);
	return typedArray.buffer;
}

//组装写入命令
function writeCommand(start, value) {
	var d = top + write + start + value;
	var crc16 = CRC.ToModbusCRC16(d);
	d = d + crc16;

	var typedArray = new Uint8Array(d.match(/[\da-f]{2}/gi).map(function(h) {
		return parseInt(h, 16)
	}));
	//console.log(typedArray);
	return typedArray.buffer;
}

//arrayBuffer转16进制字符串
function ab2hex(buffer) {
	const hexArr = Array.prototype.map.call(
		new Uint8Array(buffer),
		function(bit) {
			return ('00' + bit.toString(16)).slice(-2)
		}
	)
	return hexArr.join('');
}

//验证CRC16
function checkCRC16(str) {
	if (!str) {
		return false;
	}
	str = str.toUpperCase();
	if (str.length < 6) {
		return false;
	}
	var d = str.substr(0, str.length - 4);
	var f = str.substr(str.length - 4, 4);

	var crc16 = CRC.ToModbusCRC16(d);
	if (f == crc16) {
		return true;
	} else {
		return false;
	}
}

//解包
function solutionData(str, len) {
	str = str.toUpperCase();
	var packages = {};
	packages.top = str.substr(0, 2);
	packages.command = str.substr(2, 2);
	if (packages.command == '03') {
		var length = len * 2;
		packages.length = parseInt('0x' + str.substr(4, 2));
		if (packages.length != length) {
			return undefined;
		}
		var data = str.substr(6, length * 2);
		packages.data = data;
	} else if (packages.command == '06') {
		packages.start = str.substr(4, 4);
		packages.data = str.substr(8, 4);
	}
	packages.crc16 = str.substr(str.length - 4, 4);
	return packages;
}

//16进制转明文
function algorithm(name, v1) {
	name = name.toUpperCase();
	var value = 0;
	//console.log(name, v1);
	switch (name) {
		case '1003':
		case '1011':
		case '1012':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 100).toFixed(1));
			break;
		case '1004':
			//console.log(v1, '1004');
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10 - 1000).toFixed(1));
			break;
		case '1005':
		case '1006':
		case '1007':
		case '1008':
		case '1009':
		case '100A':
		case '100B':
		case '100C':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10 - 40).toFixed(1));
			break;
		case '1014':
		case '1016':
		case '2600':
		case '2601':
		case '2602':
		case '2603':
		case '2604':
			var v = hexToBitsFast(v1);
			var vArray = v.split('').reverse();
			value = vArray;
			break;
		case '100F':
			//console.log(v1);
			var h = parseInt('0x' + v1.substr(0, 2));
			var l = parseInt('0x' + v1.substr(2, 4));
			//console.log(name, h, l);
			var result = [h, l];
			return result;
			break;

			//保护参数寄存器
		case '2300': //电压V算法
		case '2302':
		case '2308':
		case '230A':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 100).toFixed(2));
			break;
		case '2310': //温度算法
		case '2312':
		case '2314':
		case '2316':
		case '2318':
		case '231A':
		case '231C':
		case '231E':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10 - 40).toFixed(1));
			break;
		case '2320': //电流A算法
		case '2322':
		case '2324':
		case '2326':
		case '2328':
		case '232A':
		case '232C':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10).toFixed(1));
			break;

			//硬件参数配置
		case '210A':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 100).toFixed(2));
			break;

		case '2110':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10).toFixed(1));
			break;

		case '2113':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10).toFixed(1));
			break;

		case '2114':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 1000).toFixed(3));
			break;

			//校准参数配置
		case '2411':
			var v = parseInt("0x" + v1);
			value = v - 1000;
			break;
		case '2420':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 100).toFixed(2));
			break;
		case '2427':
			var v = parseInt("0x" + v1);
			value = parseFloat((v / 10).toFixed(1));
			break;

		default:
			var v = parseInt("0x" + v1);
			value = v;
			break;
	}
	return value;
}

const hexMap = {
	'0': '0000',
	'1': '0001',
	'2': '0010',
	'3': '0011',
	'4': '0100',
	'5': '0101',
	'6': '0110',
	'7': '0111',
	'8': '1000',
	'9': '1001',
	'a': '1010',
	'b': '1011',
	'c': '1100',
	'd': '1101',
	'e': '1110',
	'f': '1111'
};
/**
 * @param {Object} hexStr
 * 
 * 
 */
function hexToBitsFast(hexStr) {
	return hexStr.toLowerCase()
		.split('')
		.map(c => hexMap[c] || '0000')
		.join('');
}

//明文转16进制
function encryption(name, v1) {
	name = name.toUpperCase();
	switch (name) {
		//保护参数寄存器
		case '2300': //电压V算法
		case '2302':
		case '2308':
		case '230A':
			v1 = v1 * 100;
			break;
		case '2310': //温度算法
		case '2312':
		case '2314':
		case '2316':
		case '2318':
		case '231A':
		case '231C':
		case '231E':
			v1 = v1 * 10 + 400;
			break;
		case '2320': //电流A算法
		case '2322':
		case '2324':
		case '2326':
		case '2328':
		case '232A':
		case '232C':
			v1 = v1 * 10;
			break;

			//硬件参数配置
		case '210A':
			v1 = v1 * 100;
			break;

		case '2110':
			v1 = v1 * 10;
			break;

		case '2113':
			v1 = v1 * 10;
			break;

		case '2114':
			v1 = v1 * 1000;
			break;

			//校准参数配置
		case '2411':
			v1 = v1 + 1000;
			break;
		case '2420':
			v1 = v1 * 100;
			break;
		case '2427':
			v1 = v1 * 10;
			break;
		default:

			break;
	}
	var v2 = v1.toString(16);
	if (v2 == '') {
		return '';
	}
	if (v2.indexOf('-') >= 0) {
		return '';
	}
	if (v2.length == 1) {
		return '000' + v2;
	} else if (v2.length == 2) {
		return '00' + v2;
	} else if (v2.length == 3) {
		return '0' + v2;
	} else if (v2.length == 4) {
		return v2;
	} else {
		return '';
	}
}

export default {
	WriteBase: WriteBase,
	writeToRead: writeToRead,
	writeToWrite: writeToWrite,
	readCommand: readCommand,
	bufferToHex: ab2hex,
	checkCRC16: checkCRC16,
	solutionData: solutionData,
	algorithm: algorithm,
	encryption: encryption,
	writeCommand: writeCommand
}